#ifndef B2D_SINGLETON_H
#define B2D_SINGLETON_H

#include "IUncopyable.h"

NS_B2D_BEGIN

////////////////////////////////////////////////////////////////////////////////////////////////////
/// \brief	Singleton class (also non-copyable)
/// 		Original implementation from "Game Programming Gems" book
/// 		
/// 		Deriving from this class creates a singleton object to ensure only
/// 		one object of that type is ever created. Note that it must created
/// 		and destroyed explicitly.
///
/// \tparam	T	Type of singleton object.
////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
class B2D_API Singleton
	: public IUncopyable
{
public:
	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// \brief	Get reference to singleton instance.
	///
	/// \return	.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	static T& Get(void)
	{ 
		B2D_ASSERT( nullptr != mInstance );	// Make sure it has been created
		return *mInstance;
	}
	/// \brief Get pointer to singleton instance
	static T* GetPtr(void) { return mInstance; }

public:
	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// \brief	Default constructor.
	/// 		Checks that an instance doesnt exist already and creates it.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	Singleton(void)
	{
		B2D_ASSERT( nullptr == mInstance );	// Make sure it doesnt exist yet
		mInstance = static_cast<T*>( this );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// \brief	Destructor.
	/// 		Destroy the instance  if it exists.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	~Singleton(void)
	{
		B2D_ASSERT( nullptr != mInstance ); // Make sure it has been created
		mInstance = nullptr;
	}

protected:
	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// \brief	The instance of this object.
	////////////////////////////////////////////////////////////////////////////////////////////////////
	static T* mInstance;
};

template <typename T> T* Singleton <T>::mInstance = nullptr;


NS_B2D_END

#endif